package com.cnsugar.common.jdbc;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import com.cnsugar.common.jdbc.dialect.DialectUtils;
import com.cnsugar.common.jdbc.model.BatchModel;
import com.cnsugar.common.jdbc.model.SqlModel;
import com.cnsugar.common.context.AppContext;
import com.cnsugar.common.jdbc.dialect.Dialect;
import com.cnsugar.common.jdbc.dialect.db.OracleDialect;
import com.cnsugar.common.jdbc.utils.JdbcUtils;
import com.cnsugar.common.paging.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;

/**
 * 数据库基本操作
 *
 * @Author Sugar
 * @Version 2018/12/7 13:59
 */
public class BaseJdbcDao<T> extends JdbcDaoSupport {
    protected static String JDBC_TEMPLATE = "jdbcTemplate";
    protected Logger log = LoggerFactory.getLogger(BaseJdbcDao.class);
    protected JdbcTemplate jdbcTemplate;
    private Class<T> clazz = null;

    @SuppressWarnings("unchecked")
    public BaseJdbcDao() {
        try {
            Type type = getClass().getGenericSuperclass();
            if (type instanceof ParameterizedType) {
                clazz = (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
            } else {
                clazz = (Class<T>) type;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行无返回值的存储过程
     *
     * @param callString 存储过程语句
     */
    public void execute(String callString) {
        execute(callString, getJdbcTemplate());
    }

    /**
     * 执行无返回值的存储过程
     *
     * @param callString 存储过程语句
     * @param args       参数
     */
    public void execute(String callString, Object[] args) {
        execute(callString, args, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回String类型
     *
     * @param callString 存储过程语句
     */
    public String executeForString(String callString) {
        return executeForString(callString, null, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回String类型
     *
     * @param callString 存储过程语句
     * @param args       参数
     */
    public String executeForString(String callString, Object[] args) {
        return executeForString(callString, args, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回int类型
     *
     * @param callString 存储过程语句
     */
    public int executeForInt(String callString) {
        return executeForInt(callString, null, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回int类型
     *
     * @param callString 存储过程语句
     * @param args       参数
     */
    public int executeForInt(String callString, Object[] args) {
        return executeForInt(callString, args, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回List类型
     *
     * @param callString 存储过程语句
     */
    public List<Map<String, Object>> executeForList(String callString) {
        return executeForList(callString, null, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回List类型
     *
     * @param callString 存储过程语句
     * @param args       参数
     */
    public List<Map<String, Object>> executeForList(String callString, Object[] args) {
        return executeForList(callString, args, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回Map类型
     *
     * @param callString 存储过程语句
     */
    public Map<String, Object> executeForMap(String callString) {
        return executeForMap(callString, null, getJdbcTemplate());
    }

    /**
     * 执行存储过程，返回Map类型
     *
     * @param callString 存储过程语句
     * @param args       参数
     */
    public Map<String, Object> executeForMap(String callString, Object[] args) {
        return executeForMap(callString, args, getJdbcTemplate());
    }

    /**
     * update语句
     *
     * @param wsql DDL语句
     */
    public int update(String wsql) {
        return update(wsql, null, getJdbcTemplate());
    }

    /**
     * update语句
     *
     * @param wsql DDL语句
     * @param jt   JdbcTemplate
     */
    public int update(String wsql, JdbcTemplate jt) {
        return update(wsql, null, null, jt);
    }

    /**
     * update语句
     *
     * @param wsql DDL语句
     * @param args 参数
     */
    public int update(String wsql, Object[] args) {
        return update(wsql, args, null, getJdbcTemplate());
    }

    /**
     * 增加、删除、修改表时，调用此方法
     *
     * @param wsql SQL语句
     * @param args 参数
     * @param jt   JdbcTemplate
     */
    public int update(String wsql, Object[] args, JdbcTemplate jt) {
        if (!wsql.matches("^ *(?i)(INSERT|MERGE|DELETE|UPDATE) .*")) {
            wsql = "UPDATE " + getTableName() + " SET " + wsql;
        }

        return update(wsql, args, null, jt);
    }

    /**
     * 批量更新
     *
     * @param sql
     * @param valueList
     * @param types     java.sql.Types
     * @return
     */
    public int batchUpdate(String sql, final List<Object[]> valueList, final int[] types) {
        return batchUpdate(sql, valueList, types, getJdbcTemplate());
    }

    /**
     * 批量更新
     *
     * @param sql
     * @return
     */
    public int batchUpdate(String[] sql) {
        return batchUpdate(sql, getJdbcTemplate());
    }

    /**
     * 批量更新
     *
     * @param sql
     * @param jt
     * @return
     */
    public int batchUpdate(String[] sql, JdbcTemplate jt) {
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "batchUpdate: sql=" + sql + "; parameters=" + arrayToString(sql);
            log.debug(logstr);
        }
        int[] rows = jt.batchUpdate(sql);
        int total = 0;
        for (int r : rows) {
            total += r;
        }
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "batchUpdate: sql=" + sql + "; parameters=" + arrayToString(sql);
            }
            log.info(logstr + "; rows=" + total);
        }
        return total;
    }

    /**
     * 执行insert语句
     *
     * @param wsql wsql语句
     */
    public int insert(String wsql) {
        return insert(wsql, null, getJdbcTemplate());
    }

    /**
     * 执行insert语句
     *
     * @param wsql wsql语句
     * @param args 参数
     */
    public int insert(String wsql, Object[] args) {
        return insert(wsql, args, getJdbcTemplate());
    }

    /**
     * 执行insert语句
     *
     * @param wsql wsql语句
     * @param jt   JdbcTemplate
     */
    public int insert(String wsql, JdbcTemplate jt) {
        return insert(wsql, null, jt);
    }

    /**
     * 执行insert语句
     *
     * @param wsql wsql语句
     * @param args 参数
     * @param jt   JdbcTemplate
     */
    public int insert(String wsql, Object[] args, JdbcTemplate jt) {
        if (!wsql.matches("^ *(?i)(INSERT|MERGE) .*")) {
            wsql = "INSERT INTO " + getTableName() + " " + wsql;
        }
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "insert: sql=" + wsql + "; parameters=" + arrayToString(args);
            log.debug(logstr);
        }
        int rows = jt.update(wsql, args);
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "insert: sql=" + wsql + "; parameters=" + arrayToString(args);
            }
            log.info(logstr + "; rows=" + rows);
        }
        return rows;
    }

    /**
     * 删除表中的记录
     *
     * @param wsql sql或删除条件 如：( id>? and time>?)
     * @return 返回删除的条数
     */

    public int delete(String wsql) {
        return delete(wsql, null, getJdbcTemplate());
    }

    /**
     * * 删除表中的记录
     *
     * @param wsql      sql 或 删除条件 如：( id>? and time>?)
     * @param whereArgs 条件里的参数 用来替换"?" 第1个参数，代表第1个问号；第2个参数，代表第2个问号；依此类推......
     * @return 返回删除的条数
     */
    public int delete(String wsql, Object[] whereArgs) {
        return delete(wsql, whereArgs, getJdbcTemplate());
    }

    /**
     * * 删除表中的记录
     *
     * @param wsql sql 或 删除条件 如：( id>? and time>?)
     * @param jt   SpringJdbcTemplate
     * @return 返回删除的条数
     */
    public int delete(String wsql, JdbcTemplate jt) {
        return delete(wsql, null, jt);
    }

    /**
     * * 删除表中的记录
     *
     * @param wsql      sql 或 删除条件 如：( id>? and time>?)
     * @param whereArgs 条件里的参数 用来替换"?" 第1个参数，代表第1个问号；第2个参数，代表第2个问号；依此类推......
     * @param jt        SpringJdbcTemplate
     * @return 返回删除的条数
     */
    public int delete(String wsql, Object[] whereArgs, JdbcTemplate jt) {
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "DELETE FROM " + getTableName();
        } else if (!wsql.matches("^ *(?i)DELETE .*")) {
            wsql = "DELETE FROM " + getTableName() + " WHERE " + wsql;
        }
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "delete: sql=" + wsql + "; parameters=" + arrayToString(whereArgs);
            log.debug(logstr);
        }
        int rows = 0;
        if (whereArgs != null && whereArgs.length > 0) {
            rows = jt.update(wsql, whereArgs);
        } else {
            rows = jt.update(wsql);
        }
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "delete: sql=" + wsql + "; parameters=" + arrayToString(whereArgs);
            }
            log.info(logstr + "; rows=" + rows);
        }
        return rows;
    }

    /**
     * 返回int类型
     *
     * @param wsql where条件或完整的sql
     * @return
     */
    public int queryForInt(String wsql) {
        return queryForInt(wsql, null, null, getJdbcTemplate());
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param jt
     * @return
     */
    public int queryForInt(String wsql, JdbcTemplate jt) {
        return queryForInt(wsql, null, null, jt);
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param values
     * @return
     */
    public int queryForInt(String wsql, Object[] values) {
        return queryForInt(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public int queryForInt(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForInt(wsql, values, null, jt);
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public int queryForInt(String wsql, Object[] values, int[] types) {
        return queryForInt(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回long类型
     *
     * @param wsql where条件或完整的sql
     * @return
     */
    public long queryForLong(String wsql) {
        return queryForLong(wsql, null, null, getJdbcTemplate());
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param jt
     * @return
     */
    public long queryForLong(String wsql, JdbcTemplate jt) {
        return queryForLong(wsql, null, null, jt);
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param values
     * @return
     */
    public long queryForLong(String wsql, Object[] values) {
        return queryForLong(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public long queryForLong(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForLong(wsql, values, null, jt);
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public long queryForLong(String wsql, Object[] values, int[] types) {
        return queryForLong(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回String类型
     *
     * @param wsql where条件或完整的sql
     * @return
     */
    public String queryForString(String wsql) {
        return queryForString(wsql, null, null, getJdbcTemplate());
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param jt
     * @return
     */
    public String queryForString(String wsql, JdbcTemplate jt) {
        return queryForString(wsql, null, null, jt);
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param values
     * @return
     */
    public String queryForString(String wsql, Object[] values) {
        return queryForString(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public String queryForString(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForString(wsql, values, null, jt);
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public String queryForString(String wsql, Object[] values, int[] types) {
        return queryForString(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @return
     */
    public Map<String, Object> queryForMap(String wsql) {
        return queryForMap(wsql, null, null, getJdbcTemplate());
    }

    public Map<String, Object> queryForMap(String wsql, JdbcTemplate jt) {
        return queryForMap(wsql, null, null, jt);
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @param values
     * @return
     */
    public Map<String, Object> queryForMap(String wsql, Object[] values) {
        return queryForMap(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public Map<String, Object> queryForMap(String wsql, Object[] values, int[] types) {
        return queryForMap(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public Map<String, Object> queryForMap(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForMap(wsql, values, null, jt);
    }

    /**
     * 通过SQL查询一个对象的所有信息，只返回一条记录
     *
     * @param wsql String 查询的语句
     * @return object Object 查询的结果
     */
    public T queryForObject(String wsql) {
        return queryForObject(wsql, null, null, getJdbcTemplate());
    }

    public T queryForObject(String wsql, JdbcTemplate jt) {
        return queryForObject(wsql, null, null, jt);
    }

    public T queryForObject(String wsql, Object[] values) {
        return queryForObject(wsql, values, null, getJdbcTemplate());
    }

    public T queryForObject(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForObject(wsql, values, null, jt);
    }

    public T queryForObject(String wsql, Object[] values, int[] types) {
        return queryForObject(wsql, values, types, getJdbcTemplate());
    }

    /**
     * * 通过SQL查询一个对象的所有信息，只返回一条记录
     *
     * @param wsql   String 查询的语句
     * @param values
     * @param types
     * @param jt
     * @return
     */
    public T queryForObject(String wsql, Object[] values, int[] types, JdbcTemplate jt) {
        ResultSetExtractor<T> rse = new ResultSetExtractor<T>() {
            public T extractData(ResultSet rs) throws SQLException, DataAccessException {
                if (rs.next()) {
                    return convert2Object(rs, clazz);
                }
                return null;
            }
        };
        Dialect dialect = DialectUtils.getDialect(jt);
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "SELECT * FROM " + getTableName();
            if (OracleDialect.NAME.equalsIgnoreCase(dialect.getDatabseProductName())) {
                wsql += " WHERE ROWNUM=1";
            } else {
                wsql += " LIMIT 1";
            }
        } else {
            if (!wsql.matches("^ *(?i)SELECT .*")) {
                wsql = "SELECT * FROM " + getTableName() + " WHERE " + wsql;
            }
        }

        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "queryForObject: sql=" + wsql + "; parameters=" + arrayToString(values);
            log.debug(logstr);
        }
        T t = null;
        if (values == null || values.length == 0) {
            t = jt.query(wsql, rse);
        } else if (types == null || types.length == 0) {
            t = jt.query(wsql, values, rse);
        } else {
            t = jt.query(wsql, values, types, rse);
        }
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "queryForObject: sql=" + wsql + "; parameters=" + arrayToString(values);
            }
            log.info(logstr + "; result=" + t);
        }
        return t;
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @return
     */
    public List<T> queryForList(String wsql) {
        return queryForList(wsql, null, null, null, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @param jt
     * @return
     */
    public List<T> queryForList(String wsql, JdbcTemplate jt) {
        return queryForList(wsql, null, null, null, jt);
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @param values
     * @return
     */
    public List<T> queryForList(String wsql, Object[] values) {
        return queryForList(wsql, values, null, null, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public List<T> queryForList(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForList(wsql, values, null, null, jt);
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @param orderBy
     * @return
     */
    public List<T> queryForList(String wsql, String orderBy) {
        return queryForList(wsql, null, null, orderBy, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @param values
     * @param orderBy
     * @return
     */
    public List<T> queryForList(String wsql, Object[] values, String orderBy) {
        return queryForList(wsql, values, null, orderBy, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param wsql
     * @param values
     * @param orderBy
     * @param jt
     * @return
     */
    public List<T> queryForList(String wsql, Object[] values, int[] types, String orderBy, JdbcTemplate jt) {
        ResultSetExtractor<List<T>> rse = new ResultSetExtractorImpl(clazz);
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "SELECT * FROM " + getTableName();
        } else if (!wsql.matches("^ *(?i)SELECT .*")) {
            wsql = "SELECT * FROM " + getTableName() + " WHERE " + wsql;
        }
        if (orderBy != null && !orderBy.isEmpty()) {
            wsql += " ORDER BY " + orderBy;
        }
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "queryForList: sql=" + wsql + "; parameters=" + arrayToString(values);
            log.debug(logstr);
        }
        List<T> list = null;
        if (values == null || values.length == 0) {
            list = jt.query(wsql, rse);
        } else if (types == null || types.length == 0) {
            list = jt.query(wsql, values, rse);
        } else {
            list = jt.query(wsql, values, types, rse);
        }
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "queryForList: sql=" + wsql + "; parameters=" + arrayToString(values);
            }
            log.info(logstr + "; size=" + (list == null ? 0 : list.size()));
        }
        return list;
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz <T>
     * @param sql
     * @return
     */
    public <T> List<T> queryForList(final Class<T> clazz, String sql) {
        return queryForList(clazz, sql, null, null, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     * @param sql
     * @param values
     * @return
     */
    public <T> List<T> queryForList(final Class<T> clazz, String sql, Object[] values) {
        return queryForList(clazz, sql, values, null, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     * @param sql
     * @param values
     * @param jt
     * @return
     */
    public <T> List<T> queryForList(final Class<T> clazz, String sql, Object[] values, JdbcTemplate jt) {
        return queryForList(clazz, sql, values, null, jt);
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @return
     */
    public List<Map<String, Object>> queryForMapList(String sql) {
        return queryForMapList(sql, null, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @param values
     * @return
     */
    public List<Map<String, Object>> queryForMapList(String sql, Object[] values) {
        return queryForMapList(sql, values, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public List<Map<String, Object>> queryForMapList(String wsql, Object[] values, int[] types) {
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "SELECT * FROM " + getTableName() + "";
        } else if (!wsql.matches("^ *(?i)SELECT .*")) {
            wsql = "SELECT * FROM " + getTableName() + " WHERE " + wsql;
        }
        return queryForMapList(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @param jt
     * @return
     */
    public List<Map<String, Object>> queryForMapList(String sql, JdbcTemplate jt) {
        return queryForMapList(sql, null, jt);
    }

    /**
     * 返回一个List<Map>
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public List<Map<String, Object>> queryForMapList(String wsql, Object[] values, JdbcTemplate jt) {
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "SELECT * FROM " + getTableName() + "";
        } else if (!wsql.matches("^ *(?i)SELECT .*")) {
            wsql = "SELECT * FROM " + getTableName() + " WHERE " + wsql;
        }
        return queryForMapList(wsql, values, null, jt);
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @return List<Integer>
     */
    public List<Integer> queryForIntegerList(String sql) {
        return queryForIntegerList(sql, null, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param values
     * @return List<Integer>
     */
    public List<Integer> queryForIntegerList(String sql, Object[] values) {
        return queryForIntegerList(sql, values, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param unique 返回结果是否去重 ture是
     * @return List<Integer>
     */
    public List<Integer> queryForIntegerList(String sql, final boolean unique) {
        return queryForIntegerList(sql, null, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param values
     * @param unique 返回结果是否去重 ture是
     * @return List<Integer>
     */
    public List<Integer> queryForIntegerList(String sql, Object[] values, final boolean unique) {
        return queryForIntegerList(sql, values, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @return List<Long>
     */
    public List<Long> queryForLongList(String sql) {
        return queryForLongList(sql, null, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @param values
     * @return List<Long>
     */
    public List<Long> queryForLongList(String sql, Object[] values) {
        return queryForLongList(sql, values, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @param unique 返回结果是否去重 ture是
     * @return List<Long>
     */
    public List<Long> queryForLongList(String sql, final boolean unique) {
        return queryForLongList(sql, null, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @param values
     * @param unique 返回结果是否去重 ture是
     * @return List<Long>
     */
    public List<Long> queryForLongList(String sql, Object[] values, final boolean unique) {
        return queryForLongList(sql, values, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<String>
     *
     * @param sql
     * @return List<String>
     */
    public List<String> queryForStringList(String sql) {
        return queryForStringList(sql, null, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<String>
     *
     * @param sql
     * @param values
     * @return List<String>
     */
    public List<String> queryForStringList(String sql, Object[] values) {
        return queryForStringList(sql, values, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<String>
     *
     * @param sql
     * @param unique 返回结果是否去重 ture是
     * @return List<String>
     */
    public List<String> queryForStringList(String sql, final boolean unique) {
        return queryForStringList(sql, null, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param values
     * @param unique 返回结果是否去重 ture是
     * @return List<String>
     */
    public List<String> queryForStringList(String sql, Object[] values, final boolean unique) {
        return queryForStringList(sql, values, unique, getJdbcTemplate());
    }

    /**
     * 查询分页对象
     *
     * @param page
     * @param wsql
     * @return
     */
    public Page queryForPage(Page page, String wsql) {
        return queryForPage(page, wsql, null, getJdbcTemplate());
    }

    /**
     * 查询分页对象
     *
     * @param page
     * @param wsql
     * @return
     */
    public Page queryForPage(Page page, String wsql, JdbcTemplate jt) {
        return queryForPage(page, wsql, null, jt);
    }

    /**
     * 查询分页对象
     *
     * @param page
     * @param wsql
     * @param values
     * @return
     */
    public Page queryForPage(Page page, String wsql, Object[] values) {
        return queryForPage(page, wsql, values, getJdbcTemplate());
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @return
     */
    public Page queryForMapPage(Page page, String wsql) {
        return queryForMapPage(page, wsql, null, getJdbcTemplate());
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @param jt
     * @return
     */
    public Page queryForMapPage(Page page, String wsql, JdbcTemplate jt) {
        return queryForMapPage(page, wsql, null, jt);
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @param values
     * @return
     */
    public Page queryForMapPage(Page page, String wsql, Object[] values) {
        return queryForMapPage(page, wsql, values, getJdbcTemplate());
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public Page queryForMapPage(Page page, String wsql, Object[] values,
                                JdbcTemplate jt) {
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "SELECT * FROM " + getTableName() + "";
        } else if (!wsql.matches("^ *(?i)SELECT .*")) {
            wsql = "SELECT * FROM " + getTableName() + " WHERE " + wsql;
        }

        return queryForPageWithMap(page, wsql, values, jt);
    }

    /**
     * 根据1个java对象更新数据库对应的表，表名跟类名一样
     *
     * @param object Object 需要更新的对象，这个对象是对数据库映射的一个javabean
     */
    public int update(T object) {
        return update(object, null, false, getJdbcTemplate());
    }

    /**
     * 根据1个java对象更新数据库对应的表，表名跟类名一样
     *
     * @param object Object 需要更新的对象，这个对象是对数据库映射的一个javabean
     * @param jt
     * @return
     */
    public int update(T object, JdbcTemplate jt) {
        return update(object, null, false, jt);
    }

    /**
     * 根据1个java对象更新数据库对应的表
     *
     * @param object  对象
     * @param columns 需要更新的字段名
     * @return
     */
    public int update(T object, String[] columns) {
        return update(object, columns, false, getJdbcTemplate());
    }

    /**
     * 根据1个java对象更新数据库对应的表
     *
     * @param object  对象
     * @param columns 指定要更新或忽略的字段名
     * @param ignore  true-忽略，false-更新
     * @return
     */
    public int update(T object, String[] columns, boolean ignore) {
        return update(object, columns, ignore, getJdbcTemplate());
    }

    /**
     * 根据1个java对象更新数据库对应的表
     *
     * @param object  对象
     * @param columns 限定属性
     * @param ignore  true-忽略，false-指定
     * @param jt
     * @return
     */
    public int update(T object, String[] columns, boolean ignore, JdbcTemplate jt) {
        SqlModel sqlModel;
        try {
            sqlModel = JdbcUtils.buildUpdateModel(object, columns, ignore, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return update(sqlModel.sql, sqlModel.values, sqlModel.types, jt);
    }

    /**
     * 批量更新对象
     *
     * @param list    对象列表
     * @param columns 需要更新的列名
     * @return
     */
    public int batchUpdate(List<T> list, String[] columns) {
        return batchUpdate(list, columns, getJdbcTemplate());
    }

    /**
     * 批量更新对象
     *
     * @param list 对象列表
     * @return 返回影响行数
     */
    public int batchUpdate(List<T> list) {
        return batchUpdate(list, null, getJdbcTemplate());
    }

    /**
     * 批量更新对象
     *
     * @param list 对象列表
     * @param jt
     * @return 返回影响行数
     */
    public int batchUpdate(List<T> list, JdbcTemplate jt) {
        return batchUpdate(list, null, jt);
    }

    /**
     * 批量更新对象
     *
     * @param list    对象列表
     * @param columns 需要更新的列名
     * @param jt
     * @return
     */
    public int batchUpdate(List<T> list, String[] columns, JdbcTemplate jt) {
        BatchModel model;
        try {
            model = JdbcUtils.buildBatchUpdateModel(list, columns, false, DialectUtils.getDialect(jt).getMark());
        } catch (SecurityException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException | NoSuchMethodException e) {
            throw new DbException(e);
        }
        return batchUpdate(model.sql, model.valueList, model.types, jt);
    }

    /**
     * 将一个对象插入数据库
     *
     * @param object Object 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @return 返回主键ID
     */
    public long save(T object) {
        return save(object, getJdbcTemplate());
    }

    /**
     * 将一个对象插入数据库
     *
     * @param object t 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @param jt     JdbcTemplate
     * @return 返回主键ID
     */
    public long save(T object, final JdbcTemplate jt) {
        SqlModel sqlModel;
        try {
            sqlModel = JdbcUtils.buildSaveModel(object, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return save(sqlModel.sql, sqlModel.values, sqlModel.types, sqlModel.pk, jt);
    }

    /**
     * 新增数据并返回自增主键的值
     *
     * @param sql    insert语句
     * @param values insert的值参数列表
     * @param pkName 主键字段名
     * @return
     */
    public long save(final String sql, final Object[] values, final String pkName) {
        return save(sql, values, pkName, getJdbcTemplate());
    }

    /**
     * 批量新增对象
     *
     * @param list List<T> 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @return 返回影响行数
     */
    public int batchSave(List<T> list) {
        return batchSave(list, getJdbcTemplate());
    }

    /**
     * 批量新增对象
     *
     * @param list List<T> 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @param jt   JdbcTemplate
     * @return 返回影响行数
     */
    public int batchSave(List<T> list, JdbcTemplate jt) {
        BatchModel model;
        try {
            model = JdbcUtils.buildBatchSaveModel(list, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return batchUpdate(model.sql, model.valueList, model.types, jt);
    }

    /**
     * 保存或更新对象,返回对象ID
     *
     * @param object
     * @return 返回对象ID
     */
    public boolean saveOrUpdate(T object) {
        try {
            return saveOrUpdate(object, getJdbcTemplate());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @return
     */
    public boolean exists(String wsql) {
        return exists(wsql, getJdbcTemplate());
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @param jt
     * @return
     */
    public boolean exists(String wsql, JdbcTemplate jt) {
        return exists(wsql, null, jt);
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @param values
     * @return
     */
    public boolean exists(String wsql, Object[] values) {
        return exists(wsql, values, getJdbcTemplate());
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public boolean exists(String wsql, Object[] values, JdbcTemplate jt) {
        if (wsql == null || (wsql = wsql.trim()).isEmpty()) {
            wsql = "SELECT COUNT(1) FROM " + getTableName() + "";
        } else if (!wsql.matches("^ *(?i)SELECT .*")) {
            wsql = "SELECT COUNT(1) FROM " + getTableName() + " WHERE " + wsql;
        }
        boolean flag = false;
        try {
            Integer r = jt.queryForObject(wsql, values, Integer.class);
            if (r != null && r.intValue() > 0) {
                flag = true;
            }
        } catch (EmptyResultDataAccessException e) {
        }
        if (log.isInfoEnabled()) {
            log.info("exists: sql=" + wsql + "; parameters=" + arrayToString(values) + "; result=" + flag);
        }
        return flag;
    }

    /**
     * 返回JdbcTemplate对象
     *
     * @return
     */
    public JdbcTemplate getJdbcTemplate() {
        if (jdbcTemplate != null) {
            return jdbcTemplate;
        }
        return (JdbcTemplate) AppContext.getBean(JDBC_TEMPLATE);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public String getTableName() {
        return JdbcUtils.getTableName(clazz);
    }
}
